home *** CD-ROM | disk | FTP | other *** search
- (* :Title: Analog Signal Processing Analysis *)
-
- (* :Authors: Brian Evans, James McClellan *)
-
- (*
- :Summary: Perform basic analysis on a one-dimensional continuous-time
- functions, including plotting f(t) and graphing the poles
- and zeroes of F(s).
- *)
-
- (* :Context: SignalProcessing`Analog`ASPAnalyze` *)
-
- (* :PackageVersion: 2.7 *)
-
- (*
- :Copyright: Copyright 1990-1991 by Brian L. Evans
- Georgia Tech Research Corporation
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is
- hereby granted, provided that the above copyright notice
- appear in all copies and that both that copyright notice and
- this permission notice appear in supporting documentation,
- and that the name of the Georgia Tech Research Corporation,
- Georgia Tech, or Georgia Institute of Technology not be used
- in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission. Georgia
- Tech makes no representations about the suitability of this
- software for any purpose. It is provided "as is" without
- express or implied warranty.
- *)
-
- (* :History: began -- March, 1990 (adapted from "ZTransform.m") *)
-
- (* :Keywords: signal processing, Laplace transform, pole-zero plot *)
-
- (* :Source: *)
-
- (* :Warning: *)
-
- (* :Mathematica Version: 1.2 or 2.0 *)
-
- (* :Limitation: *)
-
- (* :Functions: ASPAnalyze *)
-
-
-
- (* B E G I N P A C K A G E *)
-
- BeginPackage[ "SignalProcessing`Analog`ASPAnalyze`",
- "SignalProcessing`Analog`Fourier`",
- "SignalProcessing`Analog`LaPlace`",
- "SignalProcessing`Analog`LSupport`",
- "SignalProcessing`Support`TransSupport`",
- "SignalProcessing`Support`ROC`",
- "SignalProcessing`Support`SigProc`",
- "SignalProcessing`Support`SupCode`" ]
-
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- Off[ General::spell ];
- Off[ General::spell1 ] ];
-
-
- (* U S A G E I N F O R M A T I O N *)
-
- ASPAnalyze::usage =
- "ASPAnalyze[f, t] and ASPAnalyze[f, t, start, end] \
- will plot f(t) as a one-dimensional, continuous-time function \
- (real part shown as solid lines, imaginary part as dashed lines). \
- It will also print the strip of convergence, indicate stability \
- criteria, display the pole-zero diagram, and plot the magnitude \
- and phase responses. \
- For the two-dimensional version, t is a list of two variables \
- (like {t1, t2}) and start/end are optional two-element lists \
- specifying the range of the time-domain plot. \
- All non-variable symbols will be assigned a value of 1 when the \
- analyzer needs to generate a plot (override this by using options \
- like a -> 2)."
-
- (* E N D U S A G E I N F O R M A T I O N *)
-
-
- Begin["`Private`"]
-
-
- (* M E S S A G E S *)
-
- LaPlace::notvalid =
- "The forward bilateral LaPlace transform could not be found."
- ASPAnalyze::notinteresting =
- "Could not determine the important section of the frequency response."
- ASPAnalyze::hasval =
- "The global variable '' has value so it could not be used \
- as a transform variable; '' was used instead."
- CTFTransform::notvalid = "The forward Fourier transform could not be found."
-
-
- (* ASPAnalyzeQ *)
- ASPAnalyzeQ[start_, end_] :=
- NumberQ[N[start]] && NumberQ[N[end]] && N[end >= start]
-
- (* checkvar *)
- SetAttributes[checkvar, {HoldFirst}]
- checkvar[ xsym_, xval_, str_ ] := xsym /; SameQ[xsym, xval]
- checkvar[ xsym_, xval_, str_ ] :=
- Block [ {sym},
- sym = Unique["s"];
- Message[ ASPAnalyze::hasval, str, sym ];
- sym ]
-
- (* FourierExtent *)
- FourierExtent[freqresp_, defaultvalues_, w_, mag_] :=
- Block [ {newmag, wmax, wmin},
- newmag = mag;
- {wmin, wmax} = Extent1D[ freqresp /. defaultvalues, w ];
- Which [ SameQ[wmin, -Infinity] && SameQ[wmax, Infinity],
- wmin = wmax = 0,
- SameQ[wmin, -Infinity],
- wmin = wmax / 100,
- SameQ[wmax, Infinity],
- wmax = 100 wmin,
- True,
- newmag = Linear ];
- {wmin, wmax, newmag} ]
-
- (* LtoFreqResp *)
- LtoFreqResp[ funct_, ltrans_, defaultvalues_,
- onedflag_, polezeroflag_, lrules_ ] :=
- Block [ {lfreqresp, plotrange, polelist = {0}, rm, rp, stable},
-
- (* Print the signal and its Laplace transform *)
- Print[ funct ];
- Print[ "has the following Laplace transform:" ];
- Print[ TheFunction[ltrans] ];
-
- (* Print the Region of Convergence *)
- Print[ "The region of convergence is:"];
- rm = GetRMinus[ltrans];
- rp = GetRPlus[ltrans];
- If [ onedflag,
- Print[ rm, " < Re(s) < ", rp ],
- Print[ rm[[1]], " < Re(s1) < ", rp[[1]] ];
- Print[ rm[[2]], " < Re(s2) < ", rp[[2]] ] ];
-
- (* Print stability information *)
- stable = PrintStability[ltrans];
-
- (* From now on, the default values are used *)
- If [ ! EmptyQ[defaultvalues],
- Print[ "The default values are now being considered." ] ];
-
- (* Show the Pole-Zero Plot *)
- If [ polezeroflag,
- polelist = PoleZeroPlot[ltrans /. defaultvalues] ];
-
- lfreqresp = TheFunction[ltrans] /. lrules;
-
- If [ stable /. defaultvalues,
- Print[ "Since the signal is stable, the" ];
- Print[ "frequency response can be computed" ];
- Print[ "directly from the Laplace transform." ];
- plotrange = All,
-
- Print[ "Since the signal is not stable, the" ];
- Print[ "frequency response has no meaning, but it" ];
- Print[ "will be plotted anyway. However, the DC" ];
- Print[ "(zero-frequency) term will be Infinity which" ];
- Print[ "will generate a warning from Mathematica." ];
- plotrange = Automatic,
-
- Print[ "Even though the stability of the signal" ];
- Print[ "is not known, the frequency response will" ];
- Print[ "still be plotted." ];
- plotange = Automatic ];
-
- { lfreqresp, plotrange, polelist } ]
-
- (* formatting *)
- Format[ w ] := "w"
- Format[ w1 ] := "w1"
- Format[ w2 ] := "w2"
-
- Format[ s ] := "s"
- Format[ s1 ] := "s1"
- Format[ s2 ] := "s2"
-
-
- (* PrintDefaults *)
- PrintDefaults[oplist_, varlist_, defaultvalues_] :=
- Block [ {},
- If [ EmptyQ[oplist],
- Print[ "For plotting only, these symbols will" ];
- Print[ "be assigned a value of 1: ", varlist ],
- Print[ "For plotting only, these symbols will" ];
- Print[ "will be assigned default values:" ];
- Print[ defaultvalues ] ] ]
-
- (* PrintStability *)
- PrintStability[ltrans_] :=
- Block [ {stable},
- stable = Stable[ltrans];
- Which [ SameQ[stable, True],
- Print[ "The system is stable." ],
- SameQ[stable, False],
- Print[ "The system is not stable." ],
- True,
- Print[ "The system is stable if ", stable ] ];
- stable ]
-
-
- (* A S P A n a l y z e *)
-
- ASPAnalyze[f_, t_Symbol] := ASPAnalyze[f, t, -20]
- ASPAnalyze[f_, t_Symbol, start_] := ASPAnalyze[f, t, start, start + 40]
-
- ASPAnalyze[f_, t_Symbol, start_, end_, op___] :=
- Block [ {bogus, complexpoles, ctft, defaultvalues = {}, freqresp,
- fnumeric, ftemp, funct, ltrans, mag, oplist, plotrange = All,
- polezeroflag, polelist, stable, varlist, wmax, wmin},
-
- funct = ToContinuous[f];
- oplist = ToList[op];
-
- (* CONTINUOUS-TIME DOMAIN ANALYSIS *)
-
- (* Convert expression to plottable/functional form *)
- (* and replace constants like Pi with numerical value *)
-
- fnumeric = N[ TheFunction[funct] ];
-
- (* Find all valueless symbols besides the time variable *)
- (* The first parameter in Summation is a local symbol *)
-
- ftemp = fnumeric /.
- ( Summation[n_, l_, u_, inc_][expr_] :>
- bogus[l, u, inc, GetVariables[expr /. n -> l]] );
- varlist = Select[ GetVariables[ftemp /. oplist],
- Function[x, ! SameQ[x,t]] ];
- If [ ! EmptyQ[varlist] || ! EmptyQ[oplist],
- defaultvalues = oplist ~Join~ Map[(#1 -> 1)&, varlist];
- PrintDefaults[ oplist, varlist, defaultvalues ];
- fnumeric = fnumeric /. defaultvalues ];
-
- (* Plot the signal in the time-domain *)
-
- Print[ "Real part of the function is shown as solid lines.\n\
- Imaginary part of the function is shown as dashed lines."];
-
- polezeroflag = ( ! SameQ[fnumeric, 0] );
- SignalPlot[fnumeric, {t, start, end},
- PlotLabel -> "Continuous-Time Domain Analysis" ];
-
-
- (* LAPLACE-DOMAIN ANALYSIS *)
-
- (* Find F(s); if it exists, print it out, give stability *)
- (* information, and display a pole-zero plot. *)
-
- ltrans = LaPlace[funct, t, s];
- If [ ! SameQ[Head[ltrans], LTransData],
- Message[ LaPlace::notvalid ];
- ctft = CTFTransform[funct, t, w];
- If [ ! SameQ[Head[ctft], CTFTData],
- Message[CTFTransform::notvalid]; Return[ltrans] ];
- freqresp = TheFunction[ctft];
- wmin = wmax = 0;
- mag = Linear,
-
- { freqresp, plotrange, polelist } =
- LtoFreqResp[ funct, ltrans, defaultvalues,
- True, polezeroflag, ( s -> I w ) ];
- complexpoles = Map[Im, polelist];
- wmin = Min[ 0, Abs[complexpoles] ] / 10;
- wmax = Max[ 0, Abs[complexpoles] ] 10;
- mag = Log ];
-
- (* FREQUENCY-DOMAIN ANALYSIS *)
-
- (* Plot the interesting section of the freq. response *)
- (* That is, plot the stuff around the break points *)
-
- Print[ funct ];
- Print[ "has the following frequency response:" ];
- Print[ freqresp ];
-
- If [ wmin == 0 && wmax == 0,
- {wmin, wmax, mag} =
- FourierExtent[freqresp, defaultvalues, w, mag] ];
- If [ wmin == 0 && wmax == 0,
- Message[ ASPAnalyze::notinteresting ] ];
- If [ SameQ[wmax, 0], wmax = 10 ];
- If [ SameQ[wmin, 0], wmin = wmax/100 ];
- MagPhasePlot[ freqresp /. defaultvalues, { w, wmin, wmax },
- Domain -> Continuous, DomainScale -> Log,
- MagRangeScale -> mag, PhaseRangeScale -> Degree,
- PlotRange -> plotrange ];
-
- (* Return the Laplace transform *)
-
- ltrans /. s -> checkvar[Global`s, Global`s, "s"] ] /;
-
- ASPAnalyzeQ[start, end]
-
-
- ASPAnalyze[f_, {t1_Symbol, t2_Symbol}] := ASPAnalyze[f, {t1, t2}, {-10, -10}]
- ASPAnalyze[f_, {t1_Symbol, t2_Symbol}, start_] :=
- ASPAnalyze[f, {t1, t2}, start, start + {20, 20}]
-
- ASPAnalyze[f_, {t1_Symbol, t2_Symbol}, start_, end_, op___] :=
- Block [ {complexpoles, ctft, defaultvalues = {}, deltafuns, freqresp,
- fnumeric, ftemp, funct, ltrans, mag, oplist, plotrange = All,
- polelist = {0}, polezeroflag, slist, stable,
- tlist, varlist, wmax, wmin},
-
- oplist = ToList[op];
- tlist = { t1, t2 };
- slist = { s1, s2 };
- funct = ToContinuous[f];
-
- (* CONTINUOUS-TIME DOMAIN ANALYSIS *)
-
- (* Convert expression to plottable/functional form *)
- (* and replace constants like Pi with numerical value *)
-
- fnumeric = N[ TheFunction[funct] ];
-
- (* Find all valueless symbols besides the time variables *)
- (* The first parameter in Summation is a local symbol *)
-
- ftemp = fnumeric /.
- ( Summation[n_, l_, u_, inc_][expr_] :>
- bogus[l, u, inc, GetVariables[expr /. n -> l]] );
- varlist = Select[GetVariables[ftemp /. oplist],
- Function[x, ! SameQ[x,t1] && ! SameQ[x,t2]]];
- If [ ! EmptyQ[varlist] || ! EmptyQ[oplist],
- defaultvalues = oplist ~Join~ Map[(#1 -> 1)&, varlist];
- PrintDefaults[oplist, varlist, defaultvalues];
- fnumeric = fnumeric /. defaultvalues ];
-
- (* Plot delta functions separately from rest of function *)
-
- polezeroflag = ( ! SameQ[fnumeric, 0] );
- SignalPlot[fnumeric,
- {t1, start[[1]], end[[1]]},
- {t2, start[[2]], end[[2]]},
- PlotLabel -> "Continuous-Time Domain Analysis" ];
-
- (* LAPLACE-DOMAIN ANALYSIS *)
-
- (* Find F(s) and print it out. *)
-
- ltrans = LaPlace[funct, tlist, slist];
- If [ ! SameQ[Head[ltrans], LTransData],
- Message[ LaPlace::notvalid ];
- ctft = CTFTransform[funct, tlist, {w1, w2}];
- If [ ! SameQ[Head[ctft], CTFTData],
- Message[CTFTransform::notvalid]; Return[ltrans] ];
- freqresp = TheFunction[ctft];
- mag = Linear,
-
- { freqresp, plotrange, polelist } =
- LtoFreqResp[ funct, ltrans, defaultvalues,
- False, polezeroflag,
- { s1 -> I w1, s2 -> I w2 } ];
- mag = Log ];
-
- (* FREQUENCY-DOMAIN ANALYSIS *)
-
- (* Plot the interesting section of the freq. response *)
- (* That is, plot the stuff around the break points *)
- (* This is only possible for separable transforms. *)
-
- Print[ funct ];
- Print[ "has the following frequency response:" ];
- Print[ freqresp ];
-
- complexpoles = Map[Im, Select[polelist, NumberQ]];
- wmin = Min[ 0, Abs[complexpoles] ] / 10;
- wmax = Max[ 0, Abs[complexpoles] ] 10;
- If [ wmin == 0 && wmax == 0,
- Message[ ASPAnalyze::notinteresting ] ];
- If [ SameQ[wmax, 0], wmax = 10 ];
- If [ SameQ[wmin, 0], wmin = 1/10 ];
-
- MagPhasePlot[ freqresp /. defaultvalues,
- {w1, wmin, wmax}, {w2, wmin, wmax},
- Domain -> Continuous, DomainScale -> Log,
- MagRangeScale -> mag, PhaseRangeScale -> Degree,
- PlotRange -> plotrange ];
-
- (* Return the Laplace transform *)
-
- ltrans /. { s1 -> checkvar[Global`s1, Global`s1, "s1"],
- s2 -> checkvar[Global`s2, Global`s2, "s2"] } ] /;
-
- ASPAnalyzeQ[ start[[1]], end[[1]] ] &&
- ASPAnalyzeQ[ start[[2]], end[[2]] ]
-
-
- (* A u t o c o r r e l a t i o n *)
-
-
-
- (* E N D P A C K A G E *)
-
- End[]
- EndPackage[]
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- On[ General::spell ];
- On[ General::spell1 ] ];
-
-
- (* H E L P I N F O R M A T I O N *)
-
- Combine[SPfunctions, { ASPAnalyze } ]
- Protect[ASPAnalyze]
-
-
- (* E N D I N G M E S S A G E *)
-
- Print[ "The analog signal analyzer is now loaded." ]
- Null
-